﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using Medora.Data.Helpers;
using Medora.DataContract;
using Medora.Model.Basic;
using Medora.Model.Classifiers;
using Medora.Model.Institutions;
using Medora.Model.Persons;
using Medora.Model.Security;

namespace Medora.Data
{
    
    public class Uow : IUow, IDisposable
    {
       
        private MedoraDbContext DbContext { get; set; }
        
        protected IRepositoryProvider RepositoryProvider { get; set; }

      
        public Uow(IRepositoryProvider repositoryProvider)
        {
            CreateDbContext();

            repositoryProvider.DbContext = DbContext;
            RepositoryProvider = repositoryProvider;  
        }

       
        public void Commit()
        {
            DbContext.SaveChanges();
        }

        public IRepository<UserProfile> Users { get { return GetStandardRepo<UserProfile>(); } }
        public IRepository<Institution> Institutions { get { return GetStandardRepo<Institution>(); } }
        public IRepository<Department> Departments { get { return GetStandardRepo<Department>(); } }
        public IRepository<Position> Positions { get { return GetStandardRepo<Position>(); } }
        public IRepository<Speciality> Specialities { get { return GetStandardRepo<Speciality>(); } }
        public IRepository<Address> Addresses { get { return GetStandardRepo<Address>(); } }
        public IRepository<Country> Countries { get { return GetStandardRepo<Country>(); } }
        public IRepository<Region> Regions { get { return GetStandardRepo<Region>(); } }
        public IRepository<Place> Places { get { return GetStandardRepo<Place>(); } }
        public IProviderRepository Providers { get { return GetRepo<IProviderRepository>(); } }
        public IPersonRepository Persons { get { return GetRepo<IPersonRepository>(); } }
        
        public IRepository<Sector> Sectors { get { return GetStandardRepo<Sector>(); } }

        public IRepository<ScheduleTemplate> ScheduleTemplates { get { return GetStandardRepo<ScheduleTemplate>(); } }
        public IRepository<ScheduleTemplateItem> ScheduleTemplateItems { get { return GetStandardRepo<ScheduleTemplateItem>(); } }
        public IRepository<ScheduleItem> ScheduleItems { get { return GetRepo<IScheduleItemRepository>(); } }

        public IRepository<ScheduleType> ScheduleTypes { get { return GetStandardRepo<ScheduleType>(); } } 
        //public IFormRepository Forms { get { return GetRepo<IFormRepository>(); } }

        public IVisitRepository Visits { get { return GetRepo<IVisitRepository>(); } }
        public IRepository<Allergy> Allergies { get { return GetStandardRepo<Allergy>(); } }
        public IRepository<BadHabits> BadHabitses { get { return GetStandardRepo<BadHabits>(); } }
        public IRepository<FamilyHistory> FamilyHistories { get { return GetStandardRepo<FamilyHistory>(); } }
        public IRepository<Medication> Medications { get { return GetStandardRepo<Medication>(); } }
        public IRepository<HeightWeightMeasurement> HeightWeightMeasurements { get { return GetStandardRepo<HeightWeightMeasurement>(); } }
        public IRepository<BloodPressureMeasurement> BloodPressureMeasurements { get { return GetStandardRepo<BloodPressureMeasurement>(); } }
        public IRepository<ServiceInVisit> ServicesInVisit { get { return GetStandardRepo<ServiceInVisit>(); } }
        public IRepository<ProcedureInVisit> ProceduresInVisit { get { return GetStandardRepo<ProcedureInVisit>(); } }
        public IRepository<DiagnosisInVisit> DiagnosisInVisit { get { return GetStandardRepo<DiagnosisInVisit>(); } }
        public IRepository<Referral> Referrals { get { return GetStandardRepo<Referral>(); } }
        public IRepository<ScheduleActivity> ScheduleActivities { get { return GetStandardRepo<ScheduleActivity>(); } }


        protected void CreateDbContext()
        {
            DbContext = new MedoraDbContext();
            
            DbContext.Configuration.ProxyCreationEnabled = false;
            DbContext.Configuration.LazyLoadingEnabled = false;
            DbContext.Configuration.ValidateOnSaveEnabled = false;

            //DbContext.Configuration.AutoDetectChangesEnabled = false;
            // We won't use this performance tweak because we don't need 
            // the extra performance and, when autodetect is false,
            // we'd have to be careful. We're not being that careful.
        }

     
        private IRepository<T> GetStandardRepo<T>() where T : class
        {
            return RepositoryProvider.GetRepositoryForEntityType<T>();
        }

       
        private T GetRepo<T>() where T : class
        {
            return RepositoryProvider.GetRepository<T>();
        }

        /// <summary>
        /// Execs the stored procedure async.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="parameters">The parameters.</param>
        public  void ExecStoredProcedure(string query, List<SqlParameter> parameters)
        {
            using (var ctx = new MedoraDbContext())
            {
                ctx.Database.Connection.Open();
                DbCommand cmd = ctx.Database.Connection.CreateCommand();
                cmd.CommandText = query;
                cmd.CommandType = CommandType.StoredProcedure;
                foreach (var parameter in parameters)
                {
                    cmd.Parameters.Add(parameter);
                }
                var result= cmd.ExecuteNonQuery();
            }
        }
        

        #region IDisposable

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

      
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (DbContext != null)
                {
                    DbContext.Dispose();
                }
            }
        }

        #endregion
    }
}